﻿/*******************************************************************************
 * AAEngine
 * Copyright (c) 2010 Mike Jarosch
 *
 * This file is licensed under the terms of the MIT license, which is included
 * in the "MIT License.txt" file at the root directory of this SDK.
 ******************************************************************************/

using Microsoft.Xna.Framework;

namespace AAEngine.Engine
{
    public struct Box
    {
        float _x, _y, _width, _height;

        public Box(float x, float y, float width, float height)
        {
            _x = x;
            _y = y;
            _width = width;
            _height = height;
        }

        public Box(Vector2 min, Vector2 max)
        {
            _x = min.X;
            _y = min.Y;
            _width = max.X - min.X;
            _height = max.Y - min.Y;
        }

        public Vector2 Min
        {
            get { return new Vector2(_x, _y); }
        }

        public Vector2 Max
        {
            get { return new Vector2(_x + _width, _y + _height); }
        }

        public Vector2[] GetCorners()
        {
            Vector2[] corners = new Vector2[4];

            corners[0] = new Vector2(_x, _y);
            corners[1] = new Vector2(_x, _y + _height);
            corners[2] = new Vector2(_x + _width, _y);
            corners[3] = new Vector2(_x + _width, _y + _height);

            return corners;
        }

        public Vector2 Center
        {
            get
            {
                return new Vector2(_x + _width / 2, _y + _height / 2);
            }
        }

        public float X
        {
            get { return _x; }
            set { _x = value; }
        }

        public float Y
        {
            get { return _y; }
            set { _y = value; }
        }

        public float Width
        {
            get { return _width; }
            set { _width = value; }
        }

        public float Height
        {
            get { return _height; }
            set { _height = value; }
        }

        public float Left
        {
            get { return _x; }
        }

        public float Right
        {
            get { return _x + _width; }
        }

        public float Top
        {
            get { return _y; }
        }

        public float Bottom
        {
            get { return _y + _height; }
        }

        public void Inflate(float x, float y)
        {
            _x -= x;
            _y -= y;
            _width += x;
            _height += y;
        }

        public ContainmentType Contains(Vector2 point)
        {
            if ((Left <= point.X && point.X <= Right)
                && (Top <= point.Y && point.Y <= Bottom))
            {
                return ContainmentType.Contains;
            }
            return ContainmentType.Disjoint;
        }

        public ContainmentType Contains(Box box)
        {
            if (Right < box.Left || Left > box.Right)
            {
                return ContainmentType.Disjoint;
            }
            if (Bottom < box.Top || Top > box.Bottom)
            {
                return ContainmentType.Disjoint;
            }

            if (Left <= box.Left && Right >= box.Right && Top <= box.Top && Bottom >= box.Bottom)
            {
                return ContainmentType.Contains;
            }
            return ContainmentType.Intersects;
        }

        public bool Intersects(Box box)
        {
            if (Right < box.Left || Left > box.Right)
            {
                return false;
            }
            return Bottom >= box.Top && Top <= box.Bottom;
        }

        public Box Intersection(Box box)
        {
            Box ret = new Box();

            float thisRight = X + Width;
            float otherRight = box.X + box.Width;
            float thisBottom = Y + Height;
            float otherBottom = box.Y + box.Height;
            float x = (X > box.X) ? X : box.X;
            float y = (Y > box.Y) ? Y : box.Y;
            float right = (thisRight < otherRight) ? thisRight : otherRight;
            float bottom = (thisBottom < otherBottom) ? thisBottom : otherBottom;
            if ((right > x) && (bottom > y))
            {
                ret.X = x;
                ret.Y = y;
                ret.Width = right - x;
                ret.Width = bottom - y;
                return ret;
            }
            ret.X = 0;
            ret.Y = 0;
            ret.Width = 0;
            ret.Height = 0;
            return ret;
        }
    }
}
